home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / os2tools / bnklysrc / zsend.c < prev   
Encoding:
C/C++ Source or Header  |  1989-05-07  |  33.9 KB  |  1,000 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software <no-Inc>                   */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          No-Cost<no-tm> Software.                       */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*  Copyright (C) 1987, 1988, 1989 by Robert Hartman and Vincent Perriello  */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*                    Zmodem file transmission module                       */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*    For complete  details  of the licensing restrictions, please refer    */
  17. /*    to the License  agreement,  which  is published in its entirety in    */
  18. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.210.    */
  19. /*                                                                          */
  20. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  21. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  22. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  23. /*    NOT HAVE THESE FILES,  YOU SHOULD  IMMEDIATELY CONTACT THE AUTHORS    */
  24. /*    AT THE  ADDRESSES LISTED BELOW.  IN NO EVENT SHOULD YOU PROCEED TO    */
  25. /*    USE   THIS  FILE  WITHOUT  HAVING   ACCEPTED  THE  TERMS  OF   THE    */
  26. /*    BINKLEYTERM  LICENSING AGREEMENT,  OR SUCH OTHER  AGREEMENT AS YOU    */
  27. /*    ARE ABLE TO REACH WITH THE AUTHORS.                                   */
  28. /*                                                                          */
  29. /*                                                                          */
  30. /*    The Authors can be reached at the following addresses:                */
  31. /*                                                                          */
  32. /*    Robert C. Hartman                      Vincent E. Perriello           */
  33. /*    Spark Software                         VEP Software                   */
  34. /*    427-3 Amherst Street                   111 Carroll Street             */
  35. /*    CS2032, Suite 232                      Naugatuck, CT 06770            */
  36. /*    Nashua, NH 03061                                                      */
  37. /*                                                                          */
  38. /*    FidoNet 1:132/101                      FidoNet 1:141/491              */
  39. /*    Data    (603) 888-8179                 Data    (203) 729-7569         */
  40. /*                                                                          */
  41. /*    Please feel free to contact us at any time to share your comments     */
  42. /*    about our software and/or licensing policies.                         */
  43. /*                                                                          */
  44. /*                                                                          */
  45. /*  This module is based largely on a similar module in OPUS-CBCS V1.03b.   */
  46. /*  The original work is (C) Copyright 1986, Wynn Wagner III. The original  */
  47. /*  authors have graciously allowed us to use their code in this work.      */
  48. /*                                                                          */
  49. /*--------------------------------------------------------------------------*/
  50.  
  51.  
  52. #include <time.h>
  53. #include <io.h>
  54. #include <stdlib.h>
  55. #include <conio.h>
  56. #include <string.h>
  57.  
  58. #include "com.h"
  59. #include "xfer.h"
  60. #include "zmodem.h"
  61. #include "keybd.h"
  62. #include "sbuf.h"
  63. #include "sched.h"
  64. #include "externs.h"
  65. #include "prototyp.h"
  66.  
  67.  
  68. /*--------------------------------------------------------------------------*/
  69. /* Private routines                                                         */
  70. /*--------------------------------------------------------------------------*/
  71. static void ZS_SendBinaryHeader (unsigned short, byte *);
  72. static void ZS_32SendBinaryHeader (unsigned short, byte *);
  73. static void ZS_SendData (byte *, int, unsigned short);
  74. static void ZS_32SendData (byte *, int, unsigned short);
  75. static void ZS_SendByte (byte);
  76. static int ZS_GetReceiverInfo (void);
  77. static int ZS_SendFile (int, int);
  78. static int ZS_SendFileData (int);
  79. static int ZS_SyncWithReceiver (int);
  80. static void ZS_EndSend (void);
  81.  
  82. /*--------------------------------------------------------------------------*/
  83. /* Private data                                                             */
  84. /*--------------------------------------------------------------------------*/
  85. static FILE *Infile;                             /* Handle of file being sent*/
  86. static long Strtpos;                             /* Starting byte position of*/
  87.                                                  /* download                 */
  88. static long LastZRpos;                           /* Last error location      */
  89. static long ZRPosCount;                          /* ZRPOS repeat count       */
  90. static long Txpos;                               /* Transmitted file position*/
  91. static int Rxbuflen;                             /* Receiver's max buffer    */
  92.                                                  /* length                   */
  93. static int Rxflags;                              /* Receiver's flags         */
  94.  
  95. /*--------------------------------------------------------------------------*/
  96. /* SEND ZMODEM (send a file)                                                */
  97. /*   returns TRUE (1) for good xfer, FALSE (0) for bad                      */
  98. /*   sends one file per call; 'fsent' flags start and end of batch          */
  99. /*--------------------------------------------------------------------------*/
  100. int Send_Zmodem (fname, alias, fsent, wazoo)
  101. char *fname;
  102. char *alias;
  103. int fsent;
  104. int wazoo;
  105. {
  106.    register byte *p;
  107.    register byte *q;
  108.    struct stat f;
  109.    int i;
  110.    int rc;
  111.    char j[100];
  112.  
  113. #ifdef DEBUG
  114.    show_debug_name ("send_Zmodem");
  115. #endif
  116.  
  117.    _BRK_DISABLE ();
  118.    IN_XON_ENABLE ();
  119.  
  120.    errno =
  121.       z_size = 0;
  122.    Infile = NULL;
  123. /*   Txbuf = NULL;*/
  124.  
  125.    if (fname && !(fullscreen && un_attended))
  126.       set_xy ("");
  127.  
  128.    switch (fsent)
  129.       {
  130.       case 0:
  131.       case NOTHING_TO_DO:
  132.          if (!wazoo)
  133.             {
  134.             Z_PutString ("rz\r");
  135.             Z_PutLongIntoHeader (0L);
  136.             Z_SendHexHeader (ZRQINIT, Txhdr);
  137.             }
  138.          Rxtimeout = 200;
  139.          if (ZS_GetReceiverInfo () == ERROR)
  140.             {
  141.             XON_DISABLE ();
  142.             XON_ENABLE ();
  143.             return FALSE;
  144.             }
  145.       }
  146.  
  147.    Rxtimeout = (int) (614400L / (long) cur_baud);
  148.  
  149.    if (Rxtimeout < 100)
  150.       Rxtimeout = 100;
  151.  
  152.    if (fname == NULL)
  153.       goto Done;
  154.  
  155.    /*--------------------------------------------------------------------*/
  156.    /* Prepare the file for transmission.  Just ignore file open errors   */
  157.    /* because there may be other files that can be sent.                 */
  158.    /*--------------------------------------------------------------------*/
  159.    Filename = fname;
  160.    CLEAR_IOERR ();
  161.    Infile = fopen (Filename, read_binary);
  162.    if (got_error (OPEN_msg, Filename))
  163.       {
  164.       XON_DISABLE ();
  165.       XON_ENABLE ();
  166.       return OK;
  167.       }
  168.    if (isatty (fileno (Infile)))
  169.       {
  170.       errno = 1;
  171.       got_error (DEVICE_msg, Filename);
  172.       fclose (Infile);
  173.       XON_DISABLE ();
  174.       XON_ENABLE ();
  175.       return OK;
  176.       }
  177.  
  178. /*   Txbuf = zalloc ();*/
  179.  
  180.    /*--------------------------------------------------------------------*/
  181.    /* Send the file                                                      */
  182.    /*--------------------------------------------------------------------*/
  183.    rc = TRUE;
  184.  
  185.    /*--------------------------------------------------------------------*/
  186.    /* Display outbound filename, size, and ETA for sysop                 */
  187.    /*--------------------------------------------------------------------*/
  188.    fstat (fileno (Infile), &f);
  189.  
  190.    i = (int) (f.st_size * 10 / cur_baud + 27) / 54;
  191.    sprintf (j, "Z-Send %s, %ldb, %d min.", Filename, f.st_size, i);
  192.  
  193.    if (un_attended && fullscreen)
  194.       {
  195.       clear_filetransfer ();
  196.       sb_move (filewin, 1, 2);
  197.       sb_puts (filewin, j);
  198.       sb_show ();
  199.       }
  200.    else
  201.       {
  202.       cprintf ("%s", j);
  203.       set_xy (NULL);
  204.       locate_x += 2;
  205.       }
  206.  
  207.  
  208.    /*--------------------------------------------------------------------*/
  209.    /* Get outgoing file name; no directory path, lower case              */
  210.    /*--------------------------------------------------------------------*/
  211.    for (p = (alias != NULL) ? alias : Filename, q = Txbuf; *p;)
  212.       {
  213.       if ((*q++ = tolower (*p)) == '\\')
  214.          q = Txbuf;
  215.       p++;
  216.       }
  217.  
  218.    *q++ = '\0';
  219.    p = q;
  220.  
  221.    /*--------------------------------------------------------------------*/
  222.    /* Zero out remainder of file header packet                           */
  223.    /*--------------------------------------------------------------------*/
  224.    while (q < (Txbuf + KSIZE))
  225.       *q++ = '\0';
  226.  
  227.    /*--------------------------------------------------------------------*/
  228.    /* Store filesize, time last modified, and file mode in header packet */
  229.    /*--------------------------------------------------------------------*/
  230.    sprintf (p, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);
  231.  
  232.    /*--------------------------------------------------------------------*/
  233.    /* Transmit the filename block and { the download                 */
  234.    /*--------------------------------------------------------------------*/
  235.    throughput (0, 0L);
  236.  
  237.    /*--------------------------------------------------------------------*/
  238.    /* Check the results                                                  */
  239.    /*--------------------------------------------------------------------*/
  240.    switch (ZS_SendFile (1 + strlen (p) + (p - Txbuf), wazoo))
  241.       {
  242.       case ERROR:
  243.          /*--------------------------------------------------*/
  244.          /* Something tragic happened                        */
  245.          /*--------------------------------------------------*/
  246.          goto Err_Out;
  247.  
  248.       case OK:
  249.          /*--------------------------------------------------*/
  250.          /* File was sent                                    */
  251.          /*--------------------------------------------------*/
  252.          CLEAR_IOERR ();
  253.          fclose (Infile);
  254.          got_error (CLOSE_msg, Filename);
  255.          Infile = NULL;
  256.  
  257.          status_line ("+Sent-Z%s %s", Crc32t ? "/32" : "", Filename);
  258.  
  259.          update_files (1);
  260.          goto Done;
  261.  
  262.       case ZSKIP:
  263.          status_line ("+Remote refused %s", Filename);
  264.          rc = SPEC_COND;                /* Success but don't truncate! */
  265.          goto Done;
  266.  
  267.       default:
  268.          /*--------------------------------------------------*/
  269.          /* Ignore the problem, get next file, trust other   */
  270.          /* error handling mechanisms to deal with problems  */
  271.          /*--------------------------------------------------*/
  272.          goto Done;
  273.       }                                          /* switch */
  274.  
  275. Err_Out:
  276.    rc = FALSE;
  277.  
  278. Done:
  279.    if (Infile)
  280.       fclose (Infile);
  281. /*
  282.    if (Txbuf)
  283.       free (Txbuf);
  284. */
  285.    if (fsent < 0)
  286.       ZS_EndSend ();
  287.  
  288.    XON_DISABLE ();
  289.    XON_ENABLE ();
  290.  
  291.    return rc;
  292. }                                                /* send_Zmodem */
  293.  
  294. /*--------------------------------------------------------------------------*/
  295. /* ZS SEND BINARY HEADER                                                    */
  296. /* Send ZMODEM binary header hdr of type type                               */
  297. /*--------------------------------------------------------------------------*/
  298. static void ZS_SendBinaryHeader (type, hdr)
  299. unsigned short type;
  300. register byte *hdr;
  301. {
  302.    register unsigned short crc;
  303.    int n;
  304.  
  305. #ifdef DEBUG
  306.    show_debug_name ("ZS_SendBinaryHeader");
  307. #endif
  308.  
  309.    BUFFER_BYTE (ZPAD);
  310.    BUFFER_BYTE (ZDLE);
  311.  
  312.    if (Crc32t = Txfcs32)
  313.       ZS_32SendBinaryHeader (type, hdr);
  314.    else
  315.       {
  316.       BUFFER_BYTE (ZBIN);
  317.       ZS_SendByte ((byte) type);
  318.  
  319.       crc = Z_UpdateCRC (type, 0);
  320.  
  321.       for (n = 4; --n >= 0;)
  322.          {
  323.          ZS_SendByte (*hdr);
  324.          crc = Z_UpdateCRC (((unsigned short) (*hdr++)), crc);
  325.          }
  326.       ZS_SendByte ((byte) (crc >> 8));
  327.       ZS_SendByte ((byte) crc);
  328.  
  329.       UNBUFFER_BYTES ();
  330.       }
  331.  
  332.    if (type != ZDATA)
  333.       {
  334.       while (CARRIER && !OUT_EMPTY ())
  335.          time_release ();
  336.       if (!CARRIER)
  337.          CLEAR_OUTBOUND ();
  338.       }
  339. }                                                /* ZS_SendBinaryHeader */
  340.  
  341. /*--------------------------------------------------------------------------*/
  342. /* ZS SEND BINARY HEADER                                                    */
  343. /* Send ZMODEM binary header hdr of type type                               */
  344. /*--------------------------------------------------------------------------*/
  345. static void ZS_32SendBinaryHeader (type, hdr)
  346. unsigned short type;
  347. register byte *hdr;
  348. {
  349.    unsigned long crc;
  350.    int n;
  351.  
  352. #ifdef DEBUG
  353.    show_debug_name ("ZS_32SendBinaryHeader");
  354. #endif
  355.  
  356.    BUFFER_BYTE (ZBIN32);
  357.    ZS_SendByte ((byte) type);
  358.  
  359.    crc = 0xFFFFFFFF;
  360.    crc = Z_32UpdateCRC (type, crc);
  361.  
  362.    for (n = 4; --n >= 0;)
  363.       {
  364.       ZS_SendByte (*hdr);
  365.       crc = Z_32UpdateCRC (((unsigned short) (*hdr++)), crc);
  366.       }
  367.  
  368.    crc = ~crc;
  369.    for (n = 4; --n >= 0;)
  370.       {
  371.       ZS_SendByte ((byte) crc);
  372.       crc >>= 8;
  373.       }
  374.  
  375.    UNBUFFER_BYTES ();
  376. }                                                /* ZS_SendBinaryHeader */
  377.  
  378. /*--------------------------------------------------------------------------*/
  379. /* ZS SEND DATA                                                             */
  380. /* Send binary array buf with ending ZDLE sequence frameend                 */
  381. /*--------------------------------------------------------------------------*/
  382. static void ZS_SendData (buf, length, frameend)
  383. register byte *buf;
  384. int length;
  385. unsigned short frameend;
  386. {
  387.    register unsigned short crc;
  388.  
  389. #ifdef DEBUG
  390.    show_debug_name ("ZS_SendData");
  391. #endif
  392.  
  393.    if (Crc32t)
  394.       ZS_32SendData (buf, length, frameend);
  395.    else
  396.       {
  397.       crc = 0;
  398.       for (; --length >= 0;)
  399.          {
  400.          ZS_SendByte (*buf);
  401.          crc = Z_UpdateCRC (((unsigned short) (*buf++)), crc);
  402.          }
  403.  
  404.       BUFFER_BYTE (ZDLE);
  405.       BUFFER_BYTE ((unsigned char) frameend);
  406.       crc = Z_UpdateCRC (frameend, crc);
  407.       ZS_SendByte ((byte) (crc >> 8));
  408.       ZS_SendByte ((byte) crc);
  409.  
  410.       UNBUFFER_BYTES ();
  411.  
  412.       }
  413.  
  414.    if (frameend == ZCRCW)
  415.       {
  416.       SENDBYTE (XON);
  417.       while (CARRIER && !OUT_EMPTY ())
  418.          time_release ();
  419.       if (!CARRIER)
  420.          CLEAR_OUTBOUND ();
  421.       }
  422. }                                                /* ZS_SendData */
  423.  
  424. /*--------------------------------------------------------------------------*/
  425. /* ZS SEND DATA with 32 bit CRC                                             */
  426. /* Send binary array buf with ending ZDLE sequence frameend                 */
  427. /*--------------------------------------------------------------------------*/
  428. static void ZS_32SendData (buf, length, frameend)
  429. register byte *buf;
  430. int length;
  431. unsigned short frameend;
  432. {
  433.    unsigned long crc;
  434.  
  435. #ifdef DEBUG
  436.    show_debug_name ("ZS_32SendData");
  437. #endif
  438.  
  439.    crc = 0xFFFFFFFF;
  440.    for (; --length >= 0; ++buf)
  441.       {
  442.       ZS_SendByte (*buf);
  443.       crc = Z_32UpdateCRC (((unsigned short) (*buf)), crc);
  444.       }
  445.  
  446.    BUFFER_BYTE (ZDLE);
  447.    BUFFER_BYTE ((unsigned char) frameend);
  448.    crc = Z_32UpdateCRC (frameend, crc);
  449.  
  450.    crc = ~crc;
  451.  
  452.    for (length = 4; --length >= 0;)
  453.       {
  454.       ZS_SendByte ((byte) crc);
  455.       crc >>= 8;
  456.       }
  457.  
  458.    UNBUFFER_BYTES ();
  459.  
  460. }                                                /* ZS_SendData */
  461.  
  462. /*--------------------------------------------------------------------------*/
  463. /* ZS SEND BYTE                                                             */
  464. /* Send character c with ZMODEM escape sequence encoding.                   */
  465. /* Escape XON, XOFF. Escape CR following @ (Telenet net escape)             */
  466. /*--------------------------------------------------------------------------*/
  467. static void ZS_SendByte (c)
  468. register byte c;
  469. {
  470.    static byte lastsent;
  471.  
  472.    switch (c)
  473.       {
  474.       case 015:
  475.       case 0215:
  476.          if ((lastsent & 0x7F) != '@')
  477.             goto SendIt;
  478.       case 020:
  479.       case 021:
  480.       case 023:
  481.       case 0220:
  482.       case 0221:
  483.       case 0223:
  484.       case ZDLE:
  485.          /*--------------------------------------------------*/
  486.          /* Quoted characters                                */
  487.          /*--------------------------------------------------*/
  488.          BUFFER_BYTE (ZDLE);
  489.          c ^= 0x40;
  490.  
  491.       default:
  492.          /*--------------------------------------------------*/
  493.          /* Normal character output                          */
  494.          /*--------------------------------------------------*/
  495.    SendIt:
  496.          BUFFER_BYTE (lastsent = c);
  497.  
  498.       }                                          /* switch */
  499. }                                                /* ZS_SendByte */
  500.  
  501. /*--------------------------------------------------------------------------*/
  502. /* ZS GET RECEIVER INFO                                                     */
  503. /* Get the receiver's init parameters                                       */
  504. /*--------------------------------------------------------------------------*/
  505. static int ZS_GetReceiverInfo ()
  506. {
  507.    int n;
  508.  
  509. #ifdef DEBUG
  510.    show_debug_name ("ZS_GetReceiverInfo");
  511. #endif
  512.  
  513.    for (n = 10; --n >= 0;)
  514.       {
  515.       switch (Z_GetHeader (Rxhdr))
  516.          {
  517.          case ZCHALLENGE:
  518.             /*--------------------------------------*/
  519.             /* Echo receiver's challenge number     */
  520.             /*--------------------------------------*/
  521.             Z_PutLongIntoHeader (Rxpos);
  522.             Z_SendHexHeader (ZACK, Txhdr);
  523.             continue;
  524.  
  525.          case ZCOMMAND:
  526.             /*--------------------------------------*/
  527.             /* They didn't see our ZRQINIT          */
  528.             /*--------------------------------------*/
  529.             Z_PutLongIntoHeader (0L);
  530.             Z_SendHexHeader (ZRQINIT, Txhdr);
  531.             continue;
  532.  
  533.          case ZRINIT:
  534.             /*--------------------------------------*/
  535.             /* */
  536.             /*--------------------------------------*/
  537.             Rxflags = 0377 & Rxhdr[ZF0];
  538.             Rxbuflen = ((word) Rxhdr[ZP1] << 8) | Rxhdr[ZP0];
  539.             Txfcs32 = Rxflags & CANFC32;
  540.             return OK;
  541.  
  542.          case ZCAN:
  543.          case RCDO:
  544.          case TIMEOUT:
  545.             return ERROR;
  546.  
  547.          case ZRQINIT:
  548.             if (Rxhdr[ZF0] == ZCOMMAND)
  549.                continue;
  550.  
  551.          default:
  552.             Z_SendHexHeader (ZNAK, Txhdr);
  553.             continue;
  554.          }                                       /* switch */
  555.       }                                          /* for */
  556.  
  557.    return ERROR;
  558. }                                                /* ZS_GetReceiverInfo */
  559.  
  560. /*--------------------------------------------------------------------------*/
  561. /* ZS SEND FILE                                                             */
  562. /* Send ZFILE frame and begin sending ZDATA frame                           */
  563. /*--------------------------------------------------------------------------*/
  564. static int ZS_SendFile (blen, wazoo)
  565. int blen;
  566. int wazoo;
  567. {
  568.    register int c;
  569.    long t, timerset ();
  570.  
  571. #ifdef DEBUG
  572.    show_debug_name ("ZS_SendFile");
  573. #endif
  574.  
  575.    while (1)
  576.       {
  577.       if (got_ESC ())
  578.          {
  579.          CLEAR_OUTBOUND ();
  580.          XON_DISABLE ();                         /* Make sure xmitter is
  581.                                                   * unstuck */
  582.          send_can ();                            /* transmit at least 10 cans    */
  583.          t = timerset (200);                     /* wait no more than 2
  584.                                                   * seconds  */
  585.          while (!timeup (t) && !OUT_EMPTY () && CARRIER)
  586.             time_release ();                     /* Give up slice while
  587.                                                   * waiting  */
  588.          XON_ENABLE ();                          /* Turn XON/XOFF back on...     */
  589.          z_log (KBD_msg);
  590.          return ERROR;
  591.          }
  592.       else if (!CARRIER)
  593.          return ERROR;
  594.  
  595.       Txhdr[ZF0] = LZCONV;                       /* Default file conversion
  596.                                                   * mode */
  597.       Txhdr[ZF1] = LZMANAG;                      /* Default file management
  598.                                                   * mode */
  599.       Txhdr[ZF2] = LZTRANS;                      /* Default file transport
  600.                                                   * mode */
  601.       Txhdr[ZF3] = 0;
  602.       ZS_SendBinaryHeader (ZFILE, Txhdr);
  603.       ZS_SendData (Txbuf, blen, ZCRCW);
  604.  
  605. Again:
  606.       switch (c = Z_GetHeader (Rxhdr))
  607.          {
  608.          case ZRINIT:
  609.             while ((c = Z_GetByte (50)) > 0)
  610.                if (c == ZPAD)
  611.                   goto Again;
  612.  
  613.             /* Fall thru to */
  614.  
  615.          default:
  616.             continue;
  617.  
  618.          case ZCAN:
  619.          case RCDO:
  620.          case TIMEOUT:
  621.          case ZFIN:
  622.          case ZABORT:
  623.             return ERROR;
  624.  
  625.          case ZSKIP:
  626.             /*-----------------------------------------*/
  627.             /* Other system wants to skip this file    */
  628.             /*-----------------------------------------*/
  629.             return c;
  630.  
  631.          case ZRPOS:
  632.             /*-----------------------------------------*/
  633.             /* Resend from this position...            */
  634.             /*-----------------------------------------*/
  635.             fseek (Infile, Rxpos, SEEK_SET);
  636.             if (Rxpos != 0L)
  637.                {
  638.                status_line (":Resuming from offset %ld", Rxpos);
  639.                CLEAR_OUTBOUND ();               /* Get rid of queued data */
  640.                XON_DISABLE ();                  /* End XON/XOFF restraint */
  641.                SENDBYTE (XON);                  /* Send XON to remote     */
  642.                XON_ENABLE ();                   /* Start XON/XOFF again   */
  643.                }
  644.             LastZRpos = Strtpos = Txpos = Rxpos;
  645.             ZRPosCount = 10;
  646.             CLEAR_INBOUND ();
  647.             return ZS_SendFileData (wazoo);
  648.          }                                       /* switch */
  649.       }                                          /* while */
  650. }                                                /* ZS_SendFile */
  651.  
  652. /*--------------------------------------------------------------------------*/
  653. /* ZS SEND FILE DATA                                                        */
  654. /* Send the data in the file                                                */
  655. /*--------------------------------------------------------------------------*/
  656. static int ZS_SendFileData (wazoo)
  657. int wazoo;
  658. {
  659.    register int c, e;
  660.    word newcnt, blklen, maxblklen, goodblks, goodneeded = 1;
  661.  
  662.    long t, timerset ();
  663.  
  664. #ifdef DEBUG
  665.    show_debug_name ("ZS_SendFileData");
  666. #endif
  667.  
  668.    maxblklen = (cur_baud < 300) ? 128 : cur_baud / 300 * 256;
  669.  
  670.    if (maxblklen > WAZOOMAX)
  671.       maxblklen = WAZOOMAX;
  672.    if (!wazoo && maxblklen > KSIZE)
  673.       maxblklen = KSIZE;
  674.    if (Rxbuflen && maxblklen > Rxbuflen)
  675.       maxblklen = Rxbuflen;
  676.    blklen = maxblklen;
  677.  
  678. SomeMore:
  679.  
  680.    if (CHAR_AVAIL ())
  681.       {
  682. WaitAck:
  683.  
  684.       switch (c = ZS_SyncWithReceiver (1))
  685.          {
  686.          case ZSKIP:
  687.             /*-----------------------------------------*/
  688.             /* Skip this file                          */
  689.             /*-----------------------------------------*/
  690.             return c;
  691.  
  692.          case ZACK:
  693.             break;
  694.  
  695.          case ZRPOS:
  696.             /*-----------------------------------------*/
  697.             /* Resume at this position                 */
  698.             /*-----------------------------------------*/
  699.         blklen = ((blklen >> 2) > 64) ? blklen >> 2 : 64;
  700.             goodblks = 0;
  701.         goodneeded = ((goodneeded << 1) > 16) ? 16 : goodneeded << 1;
  702.             break;
  703.  
  704.          case ZRINIT:
  705.             /*-----------------------------------------*/
  706.             /* Receive init                            */
  707.             /*-----------------------------------------*/
  708.             if (locate_y && !(fullscreen && un_attended))
  709.                gotoxy (2, (byte) locate_y - 1);
  710.             throughput (1, Txpos - Strtpos);
  711.             return OK;
  712.  
  713.          case TIMEOUT:
  714.             /*-----------------------------------------*/
  715.             /* Timed out on message from other side    */
  716.             /*-----------------------------------------*/
  717.             break;
  718.  
  719.          default:
  720.             z_log (Cancelled_msg);
  721.             errno = 0;
  722.             fclose (Infile);
  723.             got_error (CLOSE_msg, Filename);
  724.             return ERROR;
  725.          }                                       /* switch */
  726.  
  727.       /*
  728.        * Noise probably got us here. Odds of surviving are not good. But we
  729.        * have to get unstuck in any event. 
  730.        *
  731.        */
  732.  
  733.       Z_UncorkTransmitter ();                    /* Get our side free if need
  734.                                                   * be      */
  735.       SENDBYTE (XON);                            /* Send an XON to release
  736.                                                   * other side */
  737.  
  738.       while (CHAR_AVAIL ())
  739.          {
  740.          switch (MODEM_IN ())
  741.             {
  742.             case CAN:
  743.             case RCDO:
  744.             case ZPAD:
  745.                goto WaitAck;
  746.             }                                    /* switch */
  747.          }                                       /* while */
  748.       }                                          /* while */
  749.  
  750.    newcnt = Rxbuflen;
  751.    Z_PutLongIntoHeader (Txpos);
  752.    ZS_SendBinaryHeader (ZDATA, Txhdr);
  753.  
  754.    do
  755.       {
  756.       if (((KEYPRESS ()) && (READKB () == 27)))
  757.          {
  758.          CLEAR_OUTBOUND ();
  759.          XON_DISABLE ();                         /* Make sure xmitter is
  760.                                                   * unstuck */
  761.          send_can ();                            /* transmit at least 10 cans    */
  762.          t = timerset (200);                     /* wait no more than 2
  763.                                                   * seconds  */
  764.          while (!timeup (t) && !OUT_EMPTY () && CARRIER)
  765.             time_release ();                     /* Give up slice while
  766.                                                   * waiting  */
  767.          XON_ENABLE ();                          /* Turn XON/XOFF back on...     */
  768.          z_log (KBD_msg);
  769.          goto oops;
  770.          }
  771.  
  772.       if (!CARRIER)
  773.          goto oops;
  774.  
  775.       if ((c = fread (Txbuf, 1, blklen, Infile)) != z_size)
  776.          {
  777.          if (fullscreen && un_attended)
  778.             {
  779.             sb_move (filewin, 2, 12);
  780.             sb_puts (filewin, ultoa (((unsigned long) (z_size = c)), e_input, 10));
  781.             sb_puts (filewin, "    ");
  782.             sb_show ();
  783.             }
  784.          else
  785.             {
  786.             gotoxy (locate_x + 10, locate_y);
  787.             cputs (ultoa (((unsigned long) (z_size = c)), e_input, 10));   
  788.             putch (' ');
  789.             }
  790.          }
  791.  
  792.       if (c < blklen)
  793.          e = ZCRCE;
  794.       else if (Rxbuflen && (newcnt -= c) <= 0)
  795.          e = ZCRCW;
  796.       else e = ZCRCG;
  797.  
  798.       ZS_SendData (Txbuf, c, e);
  799.  
  800.       if (fullscreen && un_attended)
  801.          {
  802.          sb_move (filewin, 2, 2);
  803.          sb_puts (filewin, ultoa (((unsigned long) Txpos), e_input, 10));
  804.          sb_puts (filewin, "  ");
  805.          sb_show ();
  806.          }
  807.       else
  808.          {
  809.          gotoxy (locate_x, locate_y);
  810.          cputs (ultoa (((unsigned long) Txpos), e_input, 10));
  811.          putch (' ');
  812.          putch (' ');
  813.          }
  814.  
  815.       Txpos += c;
  816.       if (blklen < maxblklen && ++goodblks > goodneeded)
  817.          {
  818.      blklen = ((blklen << 1) < maxblklen) ? blklen << 1 : maxblklen;
  819.          goodblks = 0;
  820.          }
  821.  
  822.       if (e == ZCRCW)
  823.          goto WaitAck;
  824.  
  825.       while (CHAR_AVAIL ())
  826.          {
  827.          switch (MODEM_IN ())
  828.             {
  829.             case CAN:
  830.             case RCDO:
  831.             case ZPAD:
  832.                /*--------------------------------------*/
  833.                /* Interruption detected;               */
  834.                /* stop sending and process complaint   */
  835.                /*--------------------------------------*/
  836.                z_message ("Trouble?");
  837.                CLEAR_OUTBOUND ();
  838.                ZS_SendData (Txbuf, 0, ZCRCE);
  839.                goto WaitAck;
  840.             }                                    /* switch */
  841.          }                                       /* while */
  842.  
  843.       }                                          /* do */
  844.    while (e == ZCRCG);
  845.  
  846.    while (1)
  847.       {
  848.       Z_PutLongIntoHeader (Txpos);
  849.       ZS_SendBinaryHeader (ZEOF, Txhdr);
  850.  
  851.       switch (ZS_SyncWithReceiver (7))
  852.          {
  853.          case ZACK:
  854.             continue;
  855.  
  856.          case ZRPOS:
  857.             /*-----------------------------------------*/
  858.             /* Resume at this position...              */
  859.             /*-----------------------------------------*/
  860.             goto SomeMore;
  861.  
  862.          case ZRINIT:
  863.             /*-----------------------------------------*/
  864.             /* Receive init                            */
  865.             /*-----------------------------------------*/
  866.             if (locate_y && !(fullscreen && un_attended))
  867.                gotoxy (2, (byte) locate_y - 1);
  868.             throughput (1, Txpos - Strtpos);
  869.             return OK;
  870.  
  871.          case ZSKIP:
  872.             /*-----------------------------------------*/
  873.             /* Request to skip the current file        */
  874.             /*-----------------------------------------*/
  875.             z_log (Skip_msg);
  876.             CLEAR_IOERR ();
  877.             fclose (Infile);
  878.             got_error (CLOSE_msg, Filename);
  879.             return c;
  880.  
  881.          default:
  882.       oops:
  883.             z_log (Cancelled_msg);
  884.             errno = 0;
  885.             fclose (Infile);
  886.             got_error (CLOSE_msg, Filename);
  887.             return ERROR;
  888.          }                                       /* switch */
  889.       }                                          /* while */
  890. }                                                /* ZS_SendFileData */
  891.  
  892. /*--------------------------------------------------------------------------*/
  893. /* ZS SYNC WITH RECEIVER                                                    */
  894. /* Respond to receiver's complaint, get back in sync with receiver          */
  895. /*--------------------------------------------------------------------------*/
  896. static int ZS_SyncWithReceiver (num_errs)
  897. int num_errs;
  898. {
  899.    register int c;
  900.    char j[50];
  901.  
  902. #ifdef DEBUG
  903.    show_debug_name ("ZS_SyncWithReceiver");
  904. #endif
  905.    while (1)
  906.       {
  907.       c = Z_GetHeader (Rxhdr);
  908.       CLEAR_INBOUND ();
  909.       switch (c)
  910.          {
  911.          case TIMEOUT:
  912.             z_message (TIME_msg);
  913.             if ((num_errs--) >= 0)
  914.                break;
  915.  
  916.          case ZCAN:
  917.          case ZABORT:
  918.          case ZFIN:
  919.          case RCDO:
  920.             z_log ("!Err");
  921.             return ERROR;
  922.  
  923.          case ZRPOS:
  924.             if (Rxpos == LastZRpos)             /* Same as last time?    */
  925.                 {
  926.                 if (!(--ZRPosCount))            /* Yup, 10 times yet?    */
  927.                     return ERROR;               /* Too many, get out     */
  928.                 }
  929.             else ZRPosCount = 10;               /* Reset repeat count    */
  930.             LastZRpos = Rxpos;                  /* Keep track of this    */
  931.  
  932.             rewind (Infile);                    /* In case file EOF seen */
  933.             fseek (Infile, Rxpos, SEEK_SET);
  934.             Txpos = Rxpos;
  935.             sprintf (j, "Resending from %s",
  936.                ultoa (((unsigned long) (Txpos)), e_input, 10));
  937.             z_message (j);
  938.             return c;
  939.  
  940.          case ZSKIP:
  941.             z_log (Skip_msg);
  942.  
  943.          case ZRINIT:
  944.             CLEAR_IOERR ();
  945.             fclose (Infile);
  946.             got_error (CLOSE_msg, Filename);
  947.             return c;
  948.  
  949.          case ZACK:
  950.             z_message (NULL);
  951.             return c;
  952.  
  953.          default:
  954.             z_message (IDUNNO_msg);
  955.             ZS_SendBinaryHeader (ZNAK, Txhdr);
  956.             continue;
  957.          }                                       /* switch */
  958.       }                                          /* while */
  959. }                                                /* ZS_SyncWithReceiver */
  960.  
  961.  
  962.  
  963.  
  964. /*--------------------------------------------------------------------------*/
  965. /* ZS END SEND                                                              */
  966. /* Say BIBI to the receiver, try to do it cleanly                           */
  967. /*--------------------------------------------------------------------------*/
  968. static void ZS_EndSend ()
  969. {
  970.  
  971. #ifdef DEBUG
  972.     show_debug_name ("ZS_EndSend");
  973. #endif
  974.  
  975.    while (1)
  976.       {
  977.       Z_PutLongIntoHeader (0L);
  978.       ZS_SendBinaryHeader (ZFIN, Txhdr);
  979.  
  980.       switch (Z_GetHeader (Rxhdr))
  981.          {
  982.          case ZFIN:
  983.             SENDBYTE ('O');
  984.             SENDBYTE ('O');
  985.             while (CARRIER && !OUT_EMPTY ())
  986.                time_release ();
  987.             if (!CARRIER)
  988.                CLEAR_OUTBOUND ();
  989.             /* fallthrough... */
  990.          case ZCAN:
  991.          case RCDO:
  992.          case TIMEOUT:
  993.             return;
  994.          }                                       /* switch */
  995.       }                                          /* while */
  996. }                                                /* ZS_EndSend */
  997.  
  998.  
  999. /* END OF FILE: zsend.c */
  1000.